Skip to content

fix(db): complete DeduplicatedLoadSubset follow-up coverage#1352

Open
samwillis wants to merge 2 commits intomainfrom
sam/followup-subset-dedupe-fixes
Open

fix(db): complete DeduplicatedLoadSubset follow-up coverage#1352
samwillis wants to merge 2 commits intomainfrom
sam/followup-subset-dedupe-fixes

Conversation

@samwillis
Copy link
Collaborator

Summary

This is a follow-up to #1348, which fixed the main unbounded WHERE growth bug by separating the request sent to the backend from the predicate recorded for tracking.

This PR finishes the remaining correctness work around DeduplicatedLoadSubset:

  • dedupe in-flight narrowed requests against the original request intent rather than the narrowed backend predicate
  • defensively clone stored orderBy and cursor options so later caller mutation cannot corrupt dedupe state
  • add regression coverage for filtered-then-unfiltered loads, repeated unfiltered loads, in-flight loadSubset({}) dedupe, and limited-query mutation safety

What Additional Work Was Done Beyond #1348

PR #1348 introduced the trackingOptions vs loadOptions split so updateTracking() no longer records narrowed NOT(...) difference predicates as if they were the original request. That fixes the main expression-growth bug.

This follow-up adds two missing pieces:

  • inflightCalls.options now stores trackingOptions instead of loadOptions. Without this, a second loadSubset({}) call arriving while the first narrowed loadSubset({}) was still in flight would compare against NOT(...) instead of the original unfiltered request and would issue an unnecessary duplicate request.
  • cloneOptions() now clones orderBy clauses and compareOptions, and shallowly clones cursor. Without this, callers mutating reused options objects after the first request could mutate limitedCalls / inflightCalls state and break later dedupe decisions.

Why This Matters

These follow-up fixes close the two gaps left after #1348:

  • the system now treats in-flight requests the same way it treats completed requests, using the original request intent for subset matching
  • stored dedupe state is no longer vulnerable to later caller mutation of pagination metadata

Together with the original #1348 fix, this makes the deduper consistent in all three places that matter:

  • backend request optimization uses the narrowed predicate
  • tracking uses the original request
  • in-flight dedupe also uses the original request

Test Plan

Checks performed for this branch:

  • pnpm vitest run packages/db/tests/query/subset-dedupe.test.ts
  • IDE diagnostics on the edited files (subset-dedupe.ts, subset-dedupe.test.ts) reported no linter errors

Regression coverage added/expanded in packages/db/tests/query/subset-dedupe.test.ts:

  • filtered IN(...) load followed by unfiltered load sets full-coverage state and dedupes later unfiltered calls
  • filtered eq(...) load followed by unfiltered load dedupes later unfiltered and filtered calls
  • repeated unfiltered loads do not keep issuing larger nested predicates
  • identical all-data requests dedupe while the first narrowed all-data request is still in flight
  • caller mutation of a reused limited-query orderBy does not mutate stored dedupe state

Made with Cursor

Finish the DeduplicatedLoadSubset follow-up by deduping in-flight narrowed requests against the original request intent and cloning stored pagination options defensively. Add regressions covering repeated unfiltered loads, filtered-then-unfiltered coverage, in-flight load-all dedupe, and caller mutation of stored limited query options.

Made-with: Cursor
@changeset-bot
Copy link

changeset-bot bot commented Mar 11, 2026

⚠️ No Changeset found

Latest commit: d8e68fc

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@samwillis samwillis requested a review from kevin-dp March 11, 2026 11:08
@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 11, 2026

More templates

@tanstack/angular-db

npm i https://pkg.pr.new/@tanstack/angular-db@1352

@tanstack/db

npm i https://pkg.pr.new/@tanstack/db@1352

@tanstack/db-ivm

npm i https://pkg.pr.new/@tanstack/db-ivm@1352

@tanstack/electric-db-collection

npm i https://pkg.pr.new/@tanstack/electric-db-collection@1352

@tanstack/offline-transactions

npm i https://pkg.pr.new/@tanstack/offline-transactions@1352

@tanstack/powersync-db-collection

npm i https://pkg.pr.new/@tanstack/powersync-db-collection@1352

@tanstack/query-db-collection

npm i https://pkg.pr.new/@tanstack/query-db-collection@1352

@tanstack/react-db

npm i https://pkg.pr.new/@tanstack/react-db@1352

@tanstack/rxdb-db-collection

npm i https://pkg.pr.new/@tanstack/rxdb-db-collection@1352

@tanstack/solid-db

npm i https://pkg.pr.new/@tanstack/solid-db@1352

@tanstack/svelte-db

npm i https://pkg.pr.new/@tanstack/svelte-db@1352

@tanstack/trailbase-db-collection

npm i https://pkg.pr.new/@tanstack/trailbase-db-collection@1352

@tanstack/vue-db

npm i https://pkg.pr.new/@tanstack/vue-db@1352

commit: ec55183

@github-actions
Copy link
Contributor

Size Change: +33 B (+0.04%)

Total Size: 93.2 kB

Filename Size Change
./packages/db/dist/esm/query/subset-dedupe.js 960 B +33 B (+3.56%)
ℹ️ View Unchanged
Filename Size
./packages/db/dist/esm/collection/change-events.js 1.39 kB
./packages/db/dist/esm/collection/changes.js 1.22 kB
./packages/db/dist/esm/collection/events.js 388 B
./packages/db/dist/esm/collection/index.js 3.32 kB
./packages/db/dist/esm/collection/indexes.js 1.1 kB
./packages/db/dist/esm/collection/lifecycle.js 1.75 kB
./packages/db/dist/esm/collection/mutations.js 2.34 kB
./packages/db/dist/esm/collection/state.js 3.49 kB
./packages/db/dist/esm/collection/subscription.js 3.71 kB
./packages/db/dist/esm/collection/sync.js 2.41 kB
./packages/db/dist/esm/deferred.js 207 B
./packages/db/dist/esm/errors.js 4.83 kB
./packages/db/dist/esm/event-emitter.js 748 B
./packages/db/dist/esm/index.js 2.72 kB
./packages/db/dist/esm/indexes/auto-index.js 742 B
./packages/db/dist/esm/indexes/base-index.js 766 B
./packages/db/dist/esm/indexes/btree-index.js 2.17 kB
./packages/db/dist/esm/indexes/lazy-index.js 1.1 kB
./packages/db/dist/esm/indexes/reverse-index.js 538 B
./packages/db/dist/esm/local-only.js 808 B
./packages/db/dist/esm/local-storage.js 2.1 kB
./packages/db/dist/esm/optimistic-action.js 359 B
./packages/db/dist/esm/paced-mutations.js 496 B
./packages/db/dist/esm/proxy.js 3.75 kB
./packages/db/dist/esm/query/builder/functions.js 733 B
./packages/db/dist/esm/query/builder/index.js 4.1 kB
./packages/db/dist/esm/query/builder/ref-proxy.js 1.05 kB
./packages/db/dist/esm/query/compiler/evaluators.js 1.43 kB
./packages/db/dist/esm/query/compiler/expressions.js 430 B
./packages/db/dist/esm/query/compiler/group-by.js 2.23 kB
./packages/db/dist/esm/query/compiler/index.js 2.05 kB
./packages/db/dist/esm/query/compiler/joins.js 2.11 kB
./packages/db/dist/esm/query/compiler/order-by.js 1.45 kB
./packages/db/dist/esm/query/compiler/select.js 1.09 kB
./packages/db/dist/esm/query/expression-helpers.js 1.43 kB
./packages/db/dist/esm/query/ir.js 673 B
./packages/db/dist/esm/query/live-query-collection.js 360 B
./packages/db/dist/esm/query/live/collection-config-builder.js 5.55 kB
./packages/db/dist/esm/query/live/collection-registry.js 264 B
./packages/db/dist/esm/query/live/collection-subscriber.js 2.42 kB
./packages/db/dist/esm/query/live/internal.js 145 B
./packages/db/dist/esm/query/optimizer.js 2.62 kB
./packages/db/dist/esm/query/predicate-utils.js 2.97 kB
./packages/db/dist/esm/query/query-once.js 359 B
./packages/db/dist/esm/scheduler.js 1.3 kB
./packages/db/dist/esm/SortedMap.js 1.3 kB
./packages/db/dist/esm/strategies/debounceStrategy.js 247 B
./packages/db/dist/esm/strategies/queueStrategy.js 428 B
./packages/db/dist/esm/strategies/throttleStrategy.js 246 B
./packages/db/dist/esm/transactions.js 2.9 kB
./packages/db/dist/esm/utils.js 924 B
./packages/db/dist/esm/utils/browser-polyfills.js 304 B
./packages/db/dist/esm/utils/btree.js 5.61 kB
./packages/db/dist/esm/utils/comparison.js 952 B
./packages/db/dist/esm/utils/cursor.js 457 B
./packages/db/dist/esm/utils/index-optimization.js 1.51 kB
./packages/db/dist/esm/utils/type-guards.js 157 B

compressed-size-action::db-package-size

@github-actions
Copy link
Contributor

Size Change: 0 B

Total Size: 3.85 kB

ℹ️ View Unchanged
Filename Size
./packages/react-db/dist/esm/index.js 225 B
./packages/react-db/dist/esm/useLiveInfiniteQuery.js 1.32 kB
./packages/react-db/dist/esm/useLiveQuery.js 1.34 kB
./packages/react-db/dist/esm/useLiveSuspenseQuery.js 559 B
./packages/react-db/dist/esm/usePacedMutations.js 401 B

compressed-size-action::react-db-package-size

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants